package com.google.code.ccr4j.extensions;

import org.apache.xmlbeans.XmlObject;

import com.google.code.ccr4j.ActorType;
import com.google.code.ccr4j.ActorType.Address;

/**
 * @see AddressHelper
 * @author aeagle
 *
 */
public class AddressHelperImpl { // sort of implements AddressHelper {

    public static Address getHomeAddress(XmlObject xmlObject) {
        checkType(xmlObject);
        return getAddress((ActorType)xmlObject, AddressHelper.HOME_ADDRESS);
    }

    public static Address getWorkAddress(XmlObject xmlObject) {
        checkType(xmlObject);
        return getAddress((ActorType)xmlObject, AddressHelper.WORK_ADDRESS);
    }

    public static void setHomeAddress(XmlObject xmlObject, Address address) {
        checkType(xmlObject);
        setAddress(address, (ActorType)xmlObject, AddressHelper.HOME_ADDRESS);
    }
    
    public static void setWorkAddress(XmlObject xmlObject, Address address) {
        checkType(xmlObject);
        setAddress(address, (ActorType)xmlObject, AddressHelper.WORK_ADDRESS);
    }
    
    private static void checkType(XmlObject xmlObject) {
        if (!(xmlObject instanceof ActorType)) {
            throw new IllegalArgumentException("Can only handle ActorType, not " + xmlObject.getClass().getName());
        }
    }
    
    /**
     * Like findAddress(), except that if no address with the given type is found, attempts to return an address
     * with no type set.
     * @param actor
     * @param type
     * @return
     */
    private static Address getAddress(ActorType actor, String type) {
        Address address = findAddress(actor, type);

        if (address != null) {
            return address;
        }
        // didn't find an address of this type, so give an address with no type
        for (Address address2 : actor.getAddressList()) {
            if (!address2.isSetType()) {
                return address2;
            }
        }
    
        // didn't find it...
        return null;
    }

    /**
     * Find an address of the given type under this actor. If there isn't one, returns null.
     * @param actor
     * @param type
     * @return
     */
    private static Address findAddress(ActorType actor, String type) {
        for (Address address : actor.getAddressList()) {
            if (address.isSetType()) {
                if (type.equals(address.getType().getText())) {
                    return address;
                }
            }
        }
        return null;
    }
    
    /**
     * Set the address into the actor as an address with the given type. If an address of that type is already present, 
     * replace it.
     * @param address
     * @param actor
     * @param addressType
     */
    private static void setAddress(Address address, ActorType actor, String addressType) {
        Address existingAddress = findAddress(actor, addressType);
        if (existingAddress != null) {
            existingAddress.set(address);
        } else {
            Address newAddress = actor.addNewAddress();
            newAddress.set(address);
            newAddress.addNewType().setText(addressType);
        }
    }

}
